using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using UnityEngine;

public class StockYijianfenghouRanges:StockSubData
{
    public List<YijianfenghouRange> transitionsRanges;
}
public class YijianfenghouRange
{
    public int ruChangIndex;
    public int goUpTopIndex;
    public int posanIndex;
    public List<TransitionData> transitions;
}

public class YijianfenghouResult
{
    public float averGoUpRate;
}


public class YijianfenghouAnalysis : BatchProcessor
{
    private static string stocksYijianfenghouDir(int fromYear)  => StockDataAnalysis.dataOutputDir + $"Yijianfenghou/{fromYear}_{System.DateTime.Now.Year}/";
    public static string stocksYijianfenghouPath(int fromYear, string stockCode) => stocksYijianfenghouDir(fromYear) + $"{stockCode}.json";
    public int fromYear => AppController.instance.StockDataAnalysis.fromYear;

    [ContextMenu("FindAllStocksYijianfenghou")]
    void FindAllStocksYijianfenghou()
    {
        m_totalGoUpRate = 0;
        m_totalFoundCount = 0;
        actionInterval = 0.01f;
        DoActionToAllStocks(DoFindYijianFenghou);
    }

    #region test
    [NonSerialized]
    private StockAllData m_stockAllData;
    StockAllData testStockData
    {
        get
        {
            if (m_stockAllData == null || m_stockAllData.stockTransitions == null)
            {
                m_stockAllData = StocksDataController.instance.GetStockAllData(testStock,fromYear);
            }
            return m_stockAllData;
        }
    }
    public string testStock = "000001";

    [ContextMenu("TestFindYijianfenghou")]
    void TestFindYijianfenghou()
    {
        var yijianfenghou = FindYijianfenghou(testStockData);
        if (yijianfenghou != null && yijianfenghou.transitionsRanges != null && yijianfenghou.transitionsRanges.Count > 0)
        {
            var result = AnalysisYijianfenghouResult(yijianfenghou);
            Debug.LogError(
                $"${testStockData.stockData.dm} 的一剑封喉波段有{JsonConvert.SerializeObject(yijianfenghou)}, 入场后3天平均上涨：{result.averGoUpRate}");
        }
        else
        {
            Debug.LogError($"${testStockData.stockData.dm} 找不到一剑封喉波段");
        }
    }
    
    #endregion

    private int m_totalFoundCount;
    private int m_goUpCount;
    float m_totalGoUpRate = 0;
    private float averGoUpRate;
    void DoFindYijianFenghou(StockData stock)
    {
        var stockAllData = StocksDataController.instance.GetStockAllData(stock.dm,fromYear);
        var yijianfenghou = FindYijianfenghou(stockAllData);
        if (yijianfenghou != null && yijianfenghou.transitionsRanges != null && yijianfenghou.transitionsRanges.Count > 0)
        {
            var result = AnalysisYijianfenghouResult(yijianfenghou);
            Debug.Log($"${stock.dm} 的一剑封喉波段有{JsonConvert.SerializeObject(yijianfenghou)}, 入场后3天平均上涨：{result.averGoUpRate}");
            
            string str = JsonConvert.SerializeObject(yijianfenghou);
            //Debug.Log(str);
            File.WriteAllText(stocksYijianfenghouPath(fromYear, stock.dm), str);

            m_totalGoUpRate += result.averGoUpRate;
            if (result.averGoUpRate > 0)
                m_goUpCount++;
            m_totalFoundCount++;
        }
    }
    protected override void onCompleted()
    {
        if (m_totalFoundCount > 0)
        {
            float goUpPercentage = (float) m_goUpCount / m_totalFoundCount;
            float averGoUpRate = m_totalGoUpRate / m_totalFoundCount;
            string content =
                $"{m_totalFoundCount} 个一剑封喉波段,入场后2天上涨的有{m_goUpCount}个，上涨概率为：{goUpPercentage}, 平均上涨：{averGoUpRate}";
            Debug.LogError(content);
            onEnd?.Invoke(content);
        }
        else if (m_pickedStocks != null)
        {
            string content = JsonConvert.SerializeObject(m_pickedStocks);
            Debug.LogError($"选出的疑似一剑封喉波段股票有：{content}");
            onEnd?.Invoke(content);
        }
    }
    
    StockYijianfenghouRanges FindYijianfenghou(StockAllData stock, int beginTransitionIndex = 1, bool needSanshou = true,bool needHengpan = true)
    {
        Debug.Log($"FindYijianfenghou:{stock.stockData.dm}");

        if (!Directory.Exists(stocksYijianfenghouDir(fromYear)))
        {
            Directory.CreateDirectory(stocksYijianfenghouDir(fromYear));
        }

         var stockAllData = StocksDataController.instance.GetStockAllData(stock.stockData.dm, fromYear);
        if (stockAllData == null || stockAllData.stockTransitions == null)
            return null;

        var yijianfenghou = new StockYijianfenghouRanges();
        yijianfenghou.stockCode = stock.stockData.dm;
        yijianfenghou.transitionsRanges = new List<YijianfenghouRange>();
        
        var transitions = stockAllData.stockTransitions;
        for (int i = beginTransitionIndex; i < transitions.Count; i++)
        {
            if (i < 1) continue;
            
            var cur = transitions[i];
            var pre = transitions[i - 1];

            //大涨
            bool goUpTop = (cur.c - pre.c) / pre.c > 0.096f;
            if (goUpTop)
            {
                int sanpo = 0;
                //后3天内跌回涨停板的最低位
                for (int j = i+1; j <= i + 4; j++)
                {
                    if (j >= transitions.Count)
                        break;
                    
                    if(transitions[j].c < pre.c)// cur.l)
                    {
                        sanpo = j;
                        break;
                    }
                }

                int sanshou = 0;

                if (sanpo > 0)
                {
                    if (needSanshou)
                    {
                        //三破后3天内再涨回到涨停开盘价
                        for (int j = sanpo + 1; j <= sanpo + 4; j++)
                        {
                            if (j >= transitions.Count)
                                break;

                            if (transitions[j].c >= cur.o)
                            {
                                sanshou = j;
                                break;
                            }
                        }
                    }
                    else
                    {
                        //三破后3天内有上涨就行
                        for (int j = sanpo + 1; j <= sanpo + 4; j++)
                        {
                            if (j >= transitions.Count)
                                break;

                            if (transitions[j].c > transitions[sanpo].c)
                            {
                                sanshou = j;
                                break;
                            }
                        }
                        //sanshou = sanpo+1;
                    }


                    bool qianhengpan = false;
                    if (sanshou > 0)
                    {
                        if (needHengpan)
                        {
                            //涨停板前一段时间为横盘
                            double goUpTotal = 0;
                            int count = 0;
                            for (int j = i - 8; j < i; j++)
                            {
                                if (j < 0 || j >= transitions.Count)
                                    continue;

                                var jpre = j - 1;
                                if (jpre < 0 || jpre >= transitions.Count)
                                    continue;

                                double goUp = transitions[j].c - transitions[jpre].c;
                                goUpTotal += Math.Abs(goUp / transitions[jpre].c);
                                count++;
                            }

                            if (Math.Abs(goUpTotal / count) < 0.02f)
                            {
                                qianhengpan = true;
                            }
                        }
                        else
                        {
                            qianhengpan = true;
                        }
                    }

                    if (qianhengpan)
                    {
                        if (needSanshou)
                            Debug.Log($"找到一个一剑封喉入场点：{JsonConvert.SerializeObject(transitions[sanshou])}");
                        else
                            Debug.Log($"找到一个一剑封喉雏形：{transitions[i]}");

                        var yijianfenghouRange = new YijianfenghouRange();
                        var range = new List<TransitionData>();
                        for (int k = i - 5; k <= i + 10; k++)
                        {
                            if (k < 0 || k >= transitions.Count)
                                break;

                            range.Add(transitions[k]);
                        }

                        if (needSanshou)
                            yijianfenghouRange.ruChangIndex = range.IndexOf(transitions[sanshou]);
                        yijianfenghouRange.goUpTopIndex = range.IndexOf(transitions[i]);
                        yijianfenghouRange.posanIndex = range.IndexOf(transitions[sanpo]);
                        yijianfenghouRange.transitions = range;
                        yijianfenghou.transitionsRanges.Add(yijianfenghouRange);
                    }
                }
            }
        }
        return yijianfenghou;
    }

    YijianfenghouResult AnalysisYijianfenghouResult(StockYijianfenghouRanges ranges)
    {
        YijianfenghouResult result = new YijianfenghouResult();
        if (ranges.transitionsRanges != null && ranges.transitionsRanges.Count > 0)
        {
            double total = 0;
            foreach (var yijianfenghouRange in ranges.transitionsRanges)
            {
                if (yijianfenghouRange.ruChangIndex > 0 &&
                    yijianfenghouRange.ruChangIndex < yijianfenghouRange.transitions.Count)
                {
                    var ruchangDian = yijianfenghouRange.transitions[yijianfenghouRange.ruChangIndex];
                    int endIndex = yijianfenghouRange.ruChangIndex + 2;
                    if (endIndex >= yijianfenghouRange.transitions.Count)
                        endIndex = yijianfenghouRange.transitions.Count - 1;
                    double goUpRate = yijianfenghouRange.transitions[endIndex].c - ruchangDian.c;
                    total += goUpRate;
                }
            }

            result.averGoUpRate = (float) total / ranges.transitionsRanges.Count;
        }
        return result;
    }

    

    [ContextMenu("选最近一剑封喉潜在股")]
    public void PickAllYijianfenghou()
    {
        actionInterval = 0.01f;
        m_pickedStocks = new List<StockData>();
        DoActionToAllStocks(DoPickYijianFenghou);
    }

    private List<StockData> m_pickedStocks;
    
    public bool needSanshou = true;

    void DoPickYijianFenghou(StockData stock)
    {
        var stockAllData = StocksDataController.instance.GetStockAllData(stock.dm,fromYear);
        if (stockAllData == null || stockAllData.stockTransitions == null)
            return;
        
        var yijianfenghou = FindYijianfenghou(stockAllData,stockAllData.stockTransitions.Count - 10,needSanshou, true);
        if (yijianfenghou != null && yijianfenghou.transitionsRanges != null && yijianfenghou.transitionsRanges.Count > 0)
        {
            if (yijianfenghou.transitionsRanges != null && yijianfenghou.transitionsRanges.Count > 0)
            {
                Debug.LogError($"选出一剑封喉：{stock.dm} ，波段：{JsonConvert.SerializeObject(yijianfenghou)}");
                m_pickedStocks.Add(stock);
            }
        }
    }
}